package com.ygqh.baby.controller.mobile;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.controller.os.AppLoginController;
import com.ygqh.baby.po.WxAttention;
import com.ygqh.baby.po.YgOrder;
import com.ygqh.baby.po.YgUser;
import com.ygqh.baby.po.YgUserBalance;
import com.ygqh.baby.redis.RedisDao;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.impl.DocumentConstant;
import com.ygqh.baby.utils.AesCbcUtil;
import com.ygqh.baby.utils.SessionUtil;
import com.ygqh.baby.utils.WebUtils;
import com.ygqh.baby.utils.YgStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微信相关接口
 *
 * @author guohao
 */
@Controller
@RequestMapping("/mobile/small")
public class YgSmallProgramController extends BaseController {
    @Autowired
    RedisDao redisDao;
    @Autowired
    private DocumentConstant documentConstant;
    @Autowired
    private WxSmallAuthorityService wxSmallAuthorityService;
    @Autowired
    private YgOrderLogService ygOrderLogService;
    @Autowired
    private YgOrderService orderService;
    @Autowired
    private YgFrameCodeService ygFrameCodeService;
    @Autowired
    private YgOrderPaymentService orderPaymentService;
    @Autowired
    private YgUserMemberService ygUserMemberService;
    @Autowired
    private YgUserOpenService ygUserOpenService;
    @Autowired
    private YgUserBalanceService ygUserBalanceService;

    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private YgRechargeMemberRecordService ygRechargeMemberRecordService;
    @Autowired
    private WxAttentionService wxAttentionService;
    @Value("${small.appId}")
    private String wxspAppid;
    @Value("${small.secret}")
    private String wxspSecret;

    @Value("${default.head.url}")
    private String defaultHeadUrl;
    @Value("${default.nickName.prefix}")
    private String defaultNickNamePrefix;

    @Value("${wechat.pay.recharge.notify_url}")
    private String vip_notify_url;
    @Value("${wechat.pay.notify_url}")
    private String notify_url;
    @Autowired
    private YgCardCouponDetailService ygCardCouponDetailService;

    /**
     * 解密用户敏感数据（使用os下的）
     *
     * @param encryptedData 明文,加密数据
     * @param iv            加密算法的初始向量
     * @param code          用户允许登录后，回调内容会带上 code（有效期五分钟），开发者需要将 code 发送到开发者服务器后台，使用code 换取
     *                      session_key api，将 code 换成 openid 和 session_key
     * @return
     */
    @Deprecated
    @ResponseBody
    @RequestMapping(value = "/decodeUserInfo")
    public JSONPObject decodeUserInfoV2(String encryptedData, String iv, String code, String fromCode, String callback) {

        Map<String, Object> map = new HashMap<String, Object>();

        // 登录凭证不能为空
        if (code == null || code.length() == 0) {
            map.put("status", 0);
            map.put("msg", "code 不能为空");
            return new JSONPObject(callback, Message.error(map));
        }

        // 授权（必填）
        String grant_type = "authorization_code";

        // ////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid
        // ////////////////
        // 请求参数
        String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type;
        // 发送请求
        String sr = sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
        // 解析相应内容（转换成json对象）
        JSONObject json = JSONObject.parseObject(sr);
        // 获取会话密钥（session_key）
        String session_key = json.get("session_key").toString();
        // 用户的唯一标识（openid）
        String openid = (String) json.get("openid");

        // ////////////// 2、对encryptedData加密数据进行AES解密 ////////////////
        Map<String, String> userInfo = new HashMap<String, String>();

        try {
            String result = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
            if (null != result && result.length() > 0) {
                JSONObject userInfoJSON = JSONObject.parseObject(result);
                userInfo.put("openId", (String) userInfoJSON.get("openId"));
                userInfo.put("unionId", (String) userInfoJSON.get("unionId"));
                // userInfo.put("unionId", "123456");

                // 根据unionId 判断是否已经存在

                YgUser user = ygUserService.findByUuid(userInfo.get("unionId").toString());

                Boolean isBand = false;
                if (user != null) {
                    // 存在则更新smallOpenId
                    if (StringUtils.isEmpty(user.getSmallOpenId())) {
                        ygUserService.bindingOpenId(user.getId(), null, userInfo.get("openId"), userInfo.get("unionId"));
                    }
                    userInfo.put("isNewCustomer", ygUserService.isNewCustom(user.getId()).toString());
                    if (YgStringUtils.isPhoneLegal(user.getUserName())) {
                        map.put("isBand", true);
                    }
                } else {
                    // 注册
                    user = new YgUser();
                    user.setUserName(userInfoJSON.get("openId").toString());
                    user.setPassword("123456a");
                    user.setTelPhone("");
                    user.setNickName(userInfoJSON.get("nickName").toString());
                    user.setHeadImageUrl(userInfoJSON.get("avatarUrl").toString());
                    user.setSmallOpenId(userInfoJSON.get("openId").toString());
                    user.setUuid(userInfo.get("unionId").toString());
                    user.setStatus(DataStatus.Valid);
                    user.setCreateTime(new Date());
                    user.setSourceCode(user.getUserName());
                    user.setFromCode(fromCode);
                    user.setAppType(AppType.Small);
                    ygUserService.save(user);

                    YgUserBalance userBalance = new YgUserBalance();
                    userBalance.setBalancePrice(new BigDecimal("0.00"));
                    userBalance.setCreateTime(new Date());
                    userBalance.setFreezePrice(new BigDecimal("0.00"));
                    userBalance.setPreincomePrice(new BigDecimal("0.00"));
                    userBalance.setUserId(user.getId());
                    userBalance.setWithdrawPrice(new BigDecimal("0.00"));
                    ygUserBalanceService.save(userBalance);

                    userInfo.put("isNewCustomer", "true");
                    map.put("userInfo", userInfo);

                    // 注册新用户赠送拉新卡券
                    ygCardCouponDetailService.asyncGivePullNewCard(user.getId());

                    return new JSONPObject(callback, Message.success(map));
                }

                UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword());
                Subject subject = SecurityUtils.getSubject();
                subject.login(token);

                userInfo.put("userName", user.getUserName());
                userInfo.put("sessionId", subject.getSession().getId().toString());
                userInfo.put("userId", user.getId().toString());
                userInfo.put("nickName", user.getNickName());
                userInfo.put("headImageUrl", user.getHeadImageUrl());
                userInfo.put("isVip", user.isUserAgent().toString());
                map.put("userInfo", userInfo);
                map.put("isBand", isBand);
                return new JSONPObject(callback, Message.success(map));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JSONPObject(callback, Message.success(map));
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 微信统一下单
     */
    @RequestMapping(value = "UnifiedOrderJSAPI")
    @ResponseBody
    public JSONPObject UnifiedOrderJSAPI(Long orderId, BigDecimal totalPrice, String callback, HttpServletRequest request) {

        JSONPObject json = null;
        String ipAddress = WebUtils.getIpAddr(request);
        String[] split = ipAddress.split(",");
        ipAddress = split[0];
        YgUser user = SessionUtil.getCurrentUser();
        PayRequest payRequest = null;
        // 记录入参日志
        ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingPay, "small", "小程序支付：入参【orderId：" + orderId + ";totalPrice：" + totalPrice + "】");
        // 判断该订单是否已经支付过
        YgOrder ygOrder = orderService.findByOrderId(orderId);
        if (ygOrder != null && !ygOrder.getOrderStatus().equals(OrderStatus.WaitingPay)) {
            return new JSONPObject(callback, Message.success(true));
        }
        try {

            // 生成支付流水
            Long paymentCode = ygFrameCodeService.getFrameCode(CodeType.OrderPM, new Date());

            int totalFee = totalPrice.multiply(new BigDecimal(100)).intValue();
            Boolean newCustom = ygUserService.isNewCustom(user.getId(), orderId);
            // String openId = "o26750Fv0xMnvBSgFFXs7WgqzTbo";
            payRequest = wxSmallAuthorityService.createPrePay(user.getSmallOpenId(), paymentCode, totalFee, ipAddress, notify_url, null,
                    newCustom ? "newcustomer" : null);
            orderPaymentService.addPaymentRecord(BusinessModule.Order, orderId.toString(), totalPrice, paymentCode.toString(), PayType.WeChat, AppType.Small,
                    payRequest.getPrepayId(), null, null);

        } catch (Exception e) {
            ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingPay, "small", "小程序;发起微信支付失败" + e.getMessage());
            e.printStackTrace();
            return new JSONPObject(callback, Message.error(documentConstant.MESSAGE_ERROR, null));
        }
        json = new JSONPObject(callback, Message.success(payRequest));
        return json;
    }

    @RequestMapping(value = "UnifiedOrderJSAPIForVip")

    @ResponseBody
    public JSONPObject UnifiedOrderJSAPIForVip(BigDecimal vipPrice, String cardIds, Date birthday, String sourceCode, String callback, HttpServletRequest request) {

        JSONPObject json = null;
        String ipAddress = WebUtils.getIpAddr(request);
        String[] split = ipAddress.split(",");
        ipAddress = split[0];
        YgUser user = SessionUtil.getCurrentUser();
        PayRequest payRequest = null;
        StringBuilder attach = new StringBuilder();
        attach.append(user.getId()).append("-").append(CodeType.RechargeMB.name());
        try {
            vipPrice = ygUserMemberService.getVipPrice();
            Long paymentCode = ygFrameCodeService.getFrameCode(CodeType.RechargeMB, new Date());

            int totalFee = vipPrice.multiply(new BigDecimal(100)).intValue();
            payRequest = wxSmallAuthorityService.createPrePay(user.getSmallOpenId(), paymentCode, totalFee, ipAddress, vip_notify_url, attach.toString(), null);

            ygRechargeMemberRecordService.addRecord(user.getId(), paymentCode, vipPrice, "Year", PayType.WeChat, AppType.Small, sourceCode);

        } catch (Exception e) {
            e.printStackTrace();
            return new JSONPObject(callback, Message.error(documentConstant.MESSAGE_ERROR, null));
        }
        json = new JSONPObject(callback, Message.success(payRequest));
        return json;
    }

    @RequestMapping(value = "getSmallQRCode")
    @ResponseBody
    public JSONPObject getSmallQRCode(String url, String callback) {
        YgUser user = SessionUtil.getCurrentUser();
        if (StringUtils.isBlank(url)) {
            url = "pages/index/index?sourceCode=" + user.getSourceCode();
        }
        String samllQrcode = wxSmallAuthorityService.getSamllQrcode(url, 0);

        return new JSONPObject(callback, Message.success(samllQrcode));

    }

    @ResponseBody
    @RequestMapping(value = "/saveFormRecord")
    public JSONPObject saveFormRecord(String code, String formId, Integer seoId, @RequestParam(defaultValue = "0") Integer ygSeoId, Long relateId, String callback) {

        String smallOpenId = this.getSmallOpenId(code);
        WxAttention wxAttention = new WxAttention();
        wxAttention.setSeoId(seoId);
        wxAttention.setOpenId(smallOpenId);
        wxAttention.setYgSeoId(ygSeoId);
        wxAttention.setRelateId(relateId);
        wxAttention.setRecordFrom(AppType.Small);
        wxAttention.setCreateTime(new Date());
        wxAttention.setUpdateTime(wxAttention.getCreateTime());
        wxAttention.setEvent(formId);
        int save = wxAttentionService.save(wxAttention);
        return new JSONPObject(callback, Message.success(save));
    }

    private String getSmallOpenId(String code) {

        // 授权（必填）
        String grant_type = "authorization_code";

        // ////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid
        // ////////////////
        // 请求参数
        String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type;
        // 发送请求
        String sr = sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
        // 解析相应内容（转换成json对象）
        JSONObject json = JSONObject.parseObject(sr);
        // 用户的唯一标识（openid）
        String openid = (String) json.get("openid");

        return openid;
    }

}
